<?php

namespace StarCloud\Library;

use Framework\DiServices\HttpClient;
use Phalcon\Di;

class KuaiShouMiniProgram
{
    protected $appId;
    protected $secret;
    protected $access_token;

    protected $httpClient;
    protected $cacheClass;

    const API_URL_PREFIX = 'https://api.weixin.qq.com';
    const AUTH_URL = '/cgi-bin/token?';
    const CODE_2_SESSION = '/sns/jscode2session?';
    const GET_PHONE_NUMBER_URL = '/wxa/business/getuserphonenumber?';

    public function __construct()
    {
        $this->httpClient = new HttpClient(8, 5);
        $this->cacheClass = Di::getDefault()->get('redis');
    }

    /**
     * 获取access_token
     * @param string $appid 如在类初始化时已提供，则可为空
     * @param string $appsecret 如在类初始化时已提供，则可为空
     * @param string $token 手动指定access_token，非必要情况不建议用
     */
    public function checkAuth($appid='', $appsecret='', $token='')
    {
        if (!$appid || !$appsecret) {
            $appid = $this->appId;
            $appsecret = $this->secret;
        }
        if ($token) { //手动指定token，优先使用
            $this->access_token=$token;
            return $this->access_token;
        }

        $authname = 'wechat_access_token'.$appid;
        if ($rs = $this->getCache($authname)) {
            $this->access_token = $rs;
            return $rs;
        }

        $result = $this->http_get(self::API_URL_PREFIX.self::AUTH_URL.'appid='.$appid.'&secret='.$appsecret.'&grant_type=client_credential');
        Di::getDefault()->get('logger')->info("mini program api access_token result is" . $result);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json || isset($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            $this->access_token = $json['access_token'];
            $expire = $json['expires_in'] ? intval($json['expires_in'])-100 : 3600;
            $this->setCache($authname, $this->access_token, $expire);
            return $this->access_token;
        }
        return false;
    }

    /**
     * 设置缓存，按需重载
     * @param string $cachename
     * @param mixed $value
     * @param int $expired
     * @return boolean
     */
    protected function setCache($cachename, $value, $expired)
    {
        //TODO: set cache implementation
        return $this->cacheClass->set($cachename, $value, $expired);
    }

    /**
     * 获取缓存，按需重载
     * @param string $cachename
     * @return mixed
     */
    protected function getCache($cachename)
    {
        return $this->cacheClass->get($cachename);
    }

    /**
     * 清除缓存，按需重载
     * @param string $cachename
     * @return boolean
     */
    protected function removeCache($cachename)
    {
        return $this->cacheClass->del($cachename);
    }

    public function code2Session($code, $appId, $appSecret)
    {
        $code2session = [
            'js_code' => $code,
            'app_id' => $appId,
            'app_secret' => $appSecret,
        ];
        $url = "https://open.kuaishou.com/oauth2/mp/code2session";

        $result = $this->http_post($url, $code2session);

        Di::getDefault()->get('logger')->info("mini program api result is" . $result);
        if ($result) {
            $json = json_decode($result, true);
            return $json;
        }
        return false;
    }

    public function getPhoneNumber($code)
    {
        if (!$this->access_token && !$this->checkAuth()) {
            return false;
        }
        $body = json_encode([
            'code' => $code,
        ]);

        $url = self::API_URL_PREFIX. self::GET_PHONE_NUMBER_URL . 'access_token='.$this->access_token;
        $result = $this->http_post($url, $body);

        Di::getDefault()->get('logger')->info("mini program api getPhoneNumber request is " . $url . " response is" . $result);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json || !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }

            return $json;
        }
    }

    /**
     * GET 请求
     * @param string $url
     */
    private function http_get($url)
    {
        $oCurl = curl_init();
        if (stripos($url, "https://")!==false) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        if (intval($aStatus["http_code"])==200) {
            return $sContent;
        } else {
            return false;
        }
    }

    /**
     * POST 请求
     * @param string $url
     * @param array $param
     * @param boolean $post_file 是否文件上传
     * @return string content
     */
    private function http_post($url, $param, $post_file=false)
    {
        $oCurl = curl_init();
        if (stripos($url, "https://")!==false) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        if (PHP_VERSION_ID >= 50500 && class_exists('\CURLFile')) {
            $is_curlFile = true;
        } else {
            $is_curlFile = false;
            if (defined('CURLOPT_SAFE_UPLOAD')) {
                curl_setopt($oCurl, CURLOPT_SAFE_UPLOAD, false);
            }
        }
        if (is_string($param)) {
            $strPOST = $param;
        } elseif ($post_file) {
            if ($is_curlFile) {
                foreach ($param as $key => $val) {
                    if (substr($val, 0, 1) == '@') {
                        $param[$key] = new \CURLFile(realpath(substr($val, 1)));
                    }
                }
            }
            $strPOST = $param;
        } else {
            $aPOST = [];
            foreach ($param as $key=>$val) {
                $aPOST[] = $key."=".urlencode($val);
            }
            $strPOST =  join("&", $aPOST);
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_POST, true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        if (intval($aStatus["http_code"])==200) {
            return $sContent;
        } else {
            return false;
        }
    }
}
